use crate::{
    bootstrap::AppState,
    mapper,
    middleware::jwt::user::Claims,
    router::resp::RespVO,
    service::{self, order::check_out_of_range},
};
use axum::{
    body::Body,
    extract::{Path, Query, State},
    http::Response,
    response::IntoResponse,
    Json,
};
use sea_orm::sea_query::ExprTrait;
use sky_common::constant;
use sky_pojo::{
    dto::{
        self,
        order::{OrderPageQueryDTO, OrderPaymentDTO, OrderPaymentVO, OrdersSubmitDTO},
    },
    entities::order_detail,
    vo::{
        order::{OrderSubmitVO, OrderVO},
        PageResult,
    },
};

pub async fn submit(
    State(state): State<AppState>,
    claims: Claims,
    Json(dto): Json<OrdersSubmitDTO>,
) -> Response<Body> {
    // 获取当前address_id的
    let address = match service::address_book::get_by_id(&state.db_pool, dto.address_book_id).await
    {
        Ok(address) => format!(
            "{:?},{:?},{:?},{:?}",
            address.province_name, address.city_name, address.district_name, address.detail
        ),
        Err(_) => return RespVO::<()>::error_without_data("未找到地址".to_owned()).into_response(),
    };

    let out_of_range = match check_out_of_range(address).await {
        Ok(bo) => bo,
        Err(e) => {
            tracing::error!(e);
            false
        }
    };

    match out_of_range {
        true => {
            tracing::info!("{} 下单：{:?}", claims.id, dto);

            match service::order::submit_order(&state.db_pool, dto, claims.id).await {
                Ok(vo) => RespVO::<OrderSubmitVO>::success("下单成功".to_owned(), Some(vo))
                    .into_response(),
                Err(e) => RespVO::<()>::error_without_data(e).into_response(),
            }
        }
        false => RespVO::<()>::error_without_data("超出地址范围".to_owned()).into_response(),
    }
}

pub async fn payment(
    State(state): State<AppState>,
    claims: Claims,
    Json(dto): Json<OrderPaymentDTO>,
) -> Response<Body> {
    tracing::info!("订单支付 :{:?}", dto);

    match service::order::status_eq(
        &state.db_pool,
        dto.order_number.to_string(),
        constant::order::UN_PAID,
    )
    .await
    {
        Ok(bool) => match bool {
            true => match service::order::payment(&state.db_pool, dto.clone(), claims.id).await {
                Ok(_) => {}
                Err(err) => {
                    return RespVO::<()>::error_without_data(err.to_owned()).into_response()
                }
            },
            false => {
                return RespVO::<()>::error_without_data(
                    constant::message::ORDER_STATUS_ERROR.to_owned(),
                )
                .into_response()
            }
        },
        Err(e) => {
            return RespVO::<()>::error_without_data(e).into_response();
        }
    };

    let ordervo = match service::order::payment(&state.db_pool, dto, claims.id).await {
        Ok(vo) => vo,
        Err(e) => return RespVO::<()>::error_without_data(e).into_response(),
    };

    tracing::info!("生成预支付交易单 :{:?}", ordervo);

    RespVO::<serde_json::Value>::success("pay success".to_owned(), Some(ordervo)).into_response()
}

pub async fn page(
    State(state): State<AppState>,
    claims: Claims,
    Query(page_dto): Query<OrderPageQueryDTO>,
) -> Response<Body> {
    match service::order::page_query4_user(&state.db_pool, page_dto, claims.id).await {
        Ok(vec) => {
            RespVO::<PageResult<OrderVO>>::success("success".to_owned(), Some(vec)).into_response()
        }
        Err(e) => RespVO::<()>::error_without_data(e).into_response(),
    }
}

pub async fn details(
    State(state): State<AppState>,
    claims: Claims,
    Path(id): Path<i64>,
) -> Response<Body> {
    let _ = claims;
    match service::order::details(&state.db_pool, id).await {
        Ok(vo) => RespVO::<OrderVO>::success("success".to_owned(), Some(vo)).into_response(),
        Err(e) => RespVO::<()>::error_without_data(e).into_response(),
    }
}

pub async fn cancel(
    State(state): State<AppState>,
    claims: Claims,
    Path(id): Path<i64>,
) -> Response<Body> {
    tracing::info!("{} 取消了订单{}", claims.id, id);

    match service::order::user_cancel_by_id(&state.db_pool, id).await {
        Ok(_) => RespVO::<()>::success_without_data("取消成功".to_owned()).into_response(),
        Err(e) => RespVO::<()>::error_without_data(e).into_response(),
    }
}

pub async fn repetition(
    State(state): State<AppState>,
    claims: Claims,
    Path(id): Path<i64>,
) -> Response<Body> {
    match service::order::repetition(&state.db_pool, id, claims.id).await {
        Ok(_) => RespVO::<()>::success_without_data("创建成功".to_owned()).into_response(),
        Err(e) => RespVO::<()>::error_without_data(e).into_response(),
    }
}

pub async fn reminder(State(state): State<AppState>, claims: Claims, Path(id): Path<i64>) {
    service::order::reminder(&state.db_pool, id).await;
}
